package com.nuc.bigdata.service.impl;

import cn.hutool.core.date.DateTime;
import cn.hutool.core.util.IdUtil;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.nuc.bigdata.orm.dto.ShopCarGoodsDto;
import com.nuc.bigdata.orm.entity.ShopCar;
import com.nuc.bigdata.orm.entity.ShopCarGoods;
import com.nuc.bigdata.orm.feign.ShopCarFeign;
import com.nuc.bigdata.orm.feign.ShopCarGoodsFeign;
import com.nuc.bigdata.orm.mapper.ShopCarGoodsMapper;
import com.nuc.bigdata.orm.mapper.ShopCarMapper;
import com.nuc.bigdata.service.ShopCarService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.ObjectUtils;

import java.util.Date;
import java.util.LinkedList;

/**
 * @author JackLuo
 * @date 2019/12/5
 */
@Service
public class ShopCarServiceImpl implements ShopCarService {

    private final ShopCarMapper carMapper;
    private final ShopCarGoodsMapper goodsMapper;

    @Autowired
    ShopCarServiceImpl(ShopCarMapper carMapper,
                       ShopCarGoodsMapper goodsMapper) {
        this.carMapper = carMapper;
        this.goodsMapper = goodsMapper;
    }

    /**
     * 根据用户唯一标识获取购物车信息
     *
     * @param userId 用户唯一标识
     * @return 购物车实体对象
     */
    @Override
    public ShopCar queryByUserId(String userId) {
        return carMapper.selectByUserId(userId);
    }

    /**
     * 根据用户唯一标识获取购物车feign信息
     *
     * @param userId 用户唯一标识
     * @return 购物车feign实体对象
     */
    @Override
    public ShopCarFeign queryCarFeignByUserId(String userId) {
        // 判断用户有无购物车，没有就新建一个
        if (!userHavingCar(userId)) {
            ShopCar car = new ShopCar();
            car.setCreatedBy(userId);
            car.setShopCarId(IdUtil.fastSimpleUUID());
            carMapper.insert(car);
        }
        ShopCar shopCar = carMapper.selectByUserId(userId);
        return transformShopCar(shopCar);
    }

    /**
     * 添加商品到购物车
     *
     * @param goodsDto 商品dto对象
     * @param userId 用户唯一标识
     */
    @Override
    @Transactional(rollbackForClassName = "Exception")
    public void addGoodsIntoCar(ShopCarGoodsDto goodsDto,String userId) {
        ShopCar car = carMapper.selectByUserId(userId);
        String shopCarId = car.getShopCarId();
        String commodityId = goodsDto.getCommodityId();
        ShopCarGoods shopCarGoods = goodsMapper.selectByCarIdAndGoodsId(shopCarId, commodityId);
        if (!ObjectUtils.isEmpty(shopCarGoods)) {
            // 更新参数
            shopCarGoods.setCommodityQuantity(goodsDto.getCommodityQuantity());
            shopCarGoods.setUpdateTime(new Date());
            shopCarGoods.setLastUpdatedBy(userId);
            shopCarGoods.setObjectVersionNumber(shopCarGoods.getObjectVersionNumber()+1L);
            // 设置更新条件
            UpdateWrapper<ShopCarGoods> uw = new UpdateWrapper<>();
            uw.eq("shop_car_id",shopCarId );
            uw.eq("commodity_id", commodityId);
            goodsMapper.update(shopCarGoods,uw );
        }else {
            ShopCarGoods carGoods = transformGoodsDto(goodsDto, shopCarId);
            carGoods.setCreatedBy(userId);
            goodsMapper.insert(carGoods);
        }

    }

    /**
     * 移除一种商品
     *
     * @param commodityId 商品唯一标识
     * @param userId      用户唯一标识
     */
    @Override
    @Transactional(rollbackForClassName = "Exception")
    public void removeGoodsFromCar(String commodityId, String userId) {
        ShopCar car = carMapper.selectByUserId(userId);
        String shopId = car.getShopCarId();
        QueryWrapper<ShopCarGoods> wrapper = new QueryWrapper<>();
        wrapper.eq("shop_car_id",shopId );
        wrapper.eq("commodity_id",commodityId );
        goodsMapper.delete(wrapper);
    }

    /**
     * 更新购物车商品数量
     *
     * @param commodityId       商品唯一标识
     * @param userId            用户唯一标识
     * @param commodityQuantity 商品数量
     */
    @Override
    public void updateGoodsQuantity(String commodityId, String userId, Long commodityQuantity) {
        ShopCar car = carMapper.selectByUserId(userId);
        // 获取购物车id
        String shopCarId = car.getShopCarId();
        // 获取购物车中货物
        ShopCarGoods goods = goodsMapper.selectByCarIdAndGoodsId(shopCarId, commodityId);
        goods.setUpdateTime(new Date());
        goods.setLastUpdatedBy(userId);
        goods.setCommodityQuantity(commodityQuantity);
        // 更新
        UpdateWrapper<ShopCarGoods> uw = new UpdateWrapper<>();
        uw.eq("shop_car_id",shopCarId );
        uw.eq("commodity_id", commodityId);
        goodsMapper.update(goods,uw );
    }

    /**
     * 更新购物车商品是否选中
     *
     * @param commodityId 商品唯一标识
     * @param userId      用户唯一标识
     * @param selected 是否被选中
     */
    @Override
    public void updateGoodsSelected(String commodityId, String userId,Boolean selected) {
        ShopCar car = carMapper.selectByUserId(userId);
        // 获取购物车id
        String shopCarId = car.getShopCarId();
        if(carHavingGoods(shopCarId,commodityId )) {
            ShopCarGoods goods = goodsMapper.selectByCarIdAndGoodsId(shopCarId, commodityId);
            goods.setUpdateTime(new Date());
            goods.setLastUpdatedBy(userId);
            if (selected ) {
                goods.setIsDeleted(0L);
            }else {
                goods.setIsDeleted(1L);
            }
            // 更新
            UpdateWrapper<ShopCarGoods> uw = new UpdateWrapper<>();
            uw.eq("shop_car_id",shopCarId );
            uw.eq("commodity_id", commodityId);
            goodsMapper.update(goods,uw );
        }
    }

    /**
     * 判断购物车中有无指定商品
     * @param shopCarId 购物车唯一标识
     * @param commodityId 商品唯一标识
     * @return 有就返回true
     */
    private boolean carHavingGoods(String shopCarId,String commodityId) {
        ShopCarGoods shopCarGoods = goodsMapper.selectByCarIdAndGoodsId(shopCarId, commodityId);
        return !ObjectUtils.isEmpty(shopCarGoods);
    }

    /**
     * 将购物车商品信息Dto转化为商品信息实体
     * @param goodsDto 商品dto
     * @param shopCarId 购物车唯一标识
     * @return 购物车中商品实体对象
     */
    private ShopCarGoods transformGoodsDto(ShopCarGoodsDto goodsDto,String shopCarId) {
        ShopCarGoods goods = new ShopCarGoods();
        goods.setCommodityId(goodsDto.getCommodityId());
        goods.setCommodityQuantity(goodsDto.getCommodityQuantity());
        goods.setShopCarId(shopCarId);
        return goods;
    }

    /**
     * 用户有自己的购物车
     * @param userId 用户唯一标识
     * @return 有车就返回true
     */
    private boolean userHavingCar(String userId) {
        ShopCar shopCar = carMapper.selectByUserId(userId);
        return !ObjectUtils.isEmpty(shopCar);
    }


    /**
     * 将购物车转化为feign对象
     * @param car 购物车对象
     * @return 购物车feign对象
     */
    private ShopCarFeign transformShopCar(ShopCar car) {
        ShopCarFeign feign = new ShopCarFeign();
        feign.setShopCarId(car.getShopCarId());
        LinkedList<ShopCarGoodsFeign> goodsFeigns = new LinkedList<>();
        LinkedList<ShopCarGoods> goodsLinkedList = car.getGoodsLinkedList();
        goodsLinkedList.forEach(item -> goodsFeigns.add(transformShopGoods(item)));
        feign.setGoodsLinkedList(goodsFeigns);
        return feign;
    }

    /**
     * 将购物车中货物信息转化为feign
     * @param goods 货物信息
     * @return 购物车货物信息的feign对象
     */
    private ShopCarGoodsFeign transformShopGoods(ShopCarGoods goods) {
        ShopCarGoodsFeign feign = new ShopCarGoodsFeign();
        feign.setId(goods.getId());
        feign.setCommodityId(goods.getCommodityId());
        feign.setCommodityQuantity(goods.getCommodityQuantity());
        Long isDeleted = goods.getIsDeleted();
        feign.setSelected(isDeleted ==0);
        return feign;
    }
}
